package spe.ui.wizard;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CancellationException;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import org.eclipse.core.runtime.IConfigurationElement;


public class SPEProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension
{
	public static String ID = SPEProjectNewWizard.class.getName();
	
	private WizardNewProjectCreationPage mainPage;
	private SPEProjectNewWizardPage detailPage;
	private IConfigurationElement _configurationElement;
	private IProject newProject = null;
	
	public SPEProjectNewWizard()
	{
		setWindowTitle("Create New SPE Project"); //NON NLS
	}
	
	@Override
	public void init(IWorkbench wb, IStructuredSelection arg1)
	{
		//this.workbench = wb;
		setNeedsProgressMonitor(true);
	}
	
	@Override
	public void addPages()
	{
		super.addPages();
		initMainPage();
		//initDetailPage();
	}
	
	private void initMainPage()
	{
		mainPage = new WizardNewProjectCreationPage("basicNewProjectPage");
		mainPage.setTitle("New project");
		mainPage.setDescription("Create a new SPE project");
		addPage(mainPage);
	}
	
	private void initDetailPage()
	{
		detailPage = new SPEProjectNewWizardPage("detailNewProjectPage");
		addPage(detailPage);
	}

	@Override
	public boolean performFinish()
	{
		String projectName = mainPage.getProjectName();
		URI location = null;
		if(!mainPage.useDefaults())
			location = mainPage.getLocationURI();
		
		createJavaProject(projectName, location);
		
		BasicNewProjectResourceWizard.updatePerspective(_configurationElement);
		return true;
	}
	
	private void createJavaProject(String prjName, URI loc)
	{
		try{
			newProject = createNewProject();
			IJavaProject javaProject = JavaCore.create(newProject);
			createOutputLocation(javaProject);
			addJRELibraries(javaProject);
			newProject.build(IncrementalProjectBuilder.FULL_BUILD, null);
		}catch(JavaModelException je)
		{
			je.printStackTrace();
		}catch(CoreException ce)
		{
			ce.printStackTrace();
		}
	}
	
	private void createProject(IProjectDescription description, IProject projectHandler, IProgressMonitor monitor) throws CoreException 
	{
		try{
			monitor.beginTask("", 2000);
			projectHandler.create(description, new SubProgressMonitor(monitor, 1000));
			if(monitor.isCanceled())
				throw new OperationCanceledException();
			
			projectHandler.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1000));
		}finally
		{
			monitor.done();
		}
	}

	private IProject createNewProject()
	{
		final IProject newProjectHandler = mainPage.getProjectHandle();
		final IProjectDescription description = createProjectDescription(newProjectHandler);
		WorkspaceModifyOperation op = new WorkspaceModifyOperation(){

			@Override
			protected void execute(IProgressMonitor monitor) throws CoreException,
					InvocationTargetException, InterruptedException {
				
				createProject(description, newProjectHandler, monitor);
			}
			
		};
		
		//run operation
		try{
			getContainer().run(false, true, op);
			return newProjectHandler;
		}catch(InterruptedException ie)
		{
			ie.printStackTrace();
		}catch(InvocationTargetException e)
		{
			//should handle other problem
		}
		return null;
		
	}
	
	private IProjectDescription createProjectDescription(IProject projectHandler)
	{
		IPath path = null;
		if(!mainPage.useDefaults())
			path = mainPage.getLocationPath();
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IProjectDescription description = workspace.newProjectDescription(projectHandler.getName());
		description.setLocation(path);
		
		//add java nautures
		List<String> natures = new ArrayList<String>();
		natures.addAll(Arrays.asList(description.getNatureIds()));
		natures.add(JavaCore.NATURE_ID);
		description.setNatureIds(natures.toArray(new String[natures.size()]));
		
		return description;
	}
	
	private void createOutputLocation(IJavaProject javaProject) throws JavaModelException, CoreException
	{
		IFolder binFolder = javaProject.getProject().getFolder("bin");
		createFolder(binFolder);
		IPath outputLocation = binFolder.getFullPath();
		javaProject.setOutputLocation(outputLocation, null);
	}
	
	private void addJRELibraries(IJavaProject javaProject) throws JavaModelException 
	{		
		ArrayList<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
		entries.addAll(Arrays.asList(javaProject.getRawClasspath()));
		entries.addAll(Arrays.asList(PreferenceConstants.getDefaultJRELibrary()));
		javaProject.setRawClasspath((IClasspathEntry[])entries.toArray(new IClasspathEntry[entries.size()]), null);
	}
	
	private void createFolder(IFolder folder) throws CoreException {
		IContainer parent = folder.getParent();
		if (parent != null && !parent.exists() && parent instanceof IFolder) {
			createFolder((IFolder)parent);
		}
		folder.create(true, true, null);
	}
		
	@Override
    public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
        _configurationElement = config;
    }

}
